#include "imageinstance.h"

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmimgle/dcmimage.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcuid.h"

#include <QFile>

ImageInstance::ImageInstance(const QString &file):
    dcmff(0),
    dcmImage(0),
    filePath(file)
{
    dcmff = new DcmFileFormat;
    dcmff->loadFile(file.toLocal8Bit());
    initImage();
}

ImageInstance::ImageInstance(DcmFileFormat *dff):
    dcmff(dff)
{
    initImage();
}

ImageInstance::~ImageInstance()
{
    delete dcmImage;
    delete dcmff;
}

void ImageInstance::initImage()
{
    DcmDataset *dset;
    OFCondition result;
    if (dcmff && (dset = dcmff->getDataset())) {
        //patient information
        const char *value = NULL;
        result = dset->findAndGetString(DCM_PatientID, value);
        patientID = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_PatientName, value);
        patientName = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_PatientAge, value);
        patientAge = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_PatientBirthDate, value);
        patientBirth += value;

        result = dset->findAndGetString(DCM_PatientSex, value);
        patientSex = QString::fromLocal8Bit(value);

        //study information
        result = dset->findAndGetString(DCM_StudyInstanceUID, value);
        studyUid = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_StudyDate, value);
        studyTime += value;

        result = dset->findAndGetString(DCM_StudyTime, value);
        studyTime += value;

        result = dset->findAndGetString(DCM_StudyDescription, value);
        studyDes = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_ProtocolName, value);
        procId = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_BodyPartExamined, value);
        bodyPart = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_PatientPosition, value);
        bodyPos = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_Manufacturer, value);
        manufacturer = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_Modality, value);
        modality = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_ManufacturerModelName, value);
        modelName = QString::fromLocal8Bit(value);

        //series information
        result = dset->findAndGetString(DCM_SeriesInstanceUID, value);
        seriesUid = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_SeriesNumber, value);
        seriesNumber = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_SeriesDescription, value);
        seriesDes = QString::fromLocal8Bit(value);

        //instance information
        result = dset->findAndGetString(DCM_SOPClassUID, value);
        sopClassUid = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_SOPInstanceUID, value);
        instanceUid = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_InstanceNumber, value);
        instanceNumber = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_InstitutionName, value);
        institution = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_AcquisitionDate, value);
        acquisitionTime += value;

        result = dset->findAndGetString(DCM_AcquisitionTime, value);
        acquisitionTime += value;

        result = dset->findAndGetString(DCM_PatientPosition, value);
        patientPostion = QString::fromLatin1(value);

        result = dset->findAndGetString(DCM_RequestingPhysician, value);
        reqPhysician = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_PerformingPhysicianName, value);
        perPhysician = QString::fromLocal8Bit(value);

        result = dset->findAndGetString(DCM_AccessionNumber, value);
        accessionNumber = QString::fromLatin1(value);

        result = dset->findAndGetFloat64(DCM_PixelSpacing, pixelSpacingY, 0);
        result = dset->findAndGetFloat64(DCM_PixelSpacing, pixelSpacingX, 1);
        result = dset->findAndGetFloat64(DCM_SliceThickness, sliceThickness);
        result = dset->findAndGetFloat64(DCM_ImagePositionPatient, startX, 0);
        result = dset->findAndGetFloat64(DCM_ImagePositionPatient, startY, 1);
        result = dset->findAndGetFloat64(DCM_SliceLocation, sliceLocation);
        result = dset->findAndGetFloat64(DCM_RescaleIntercept, intercept);
        result = dset->findAndGetUint16(DCM_Rows, imgHeight);
        result = dset->findAndGetUint16(DCM_Columns, imgWidth);

        result = dset->findAndGetString(DCM_KVP, value);
        kvp = QString::fromLatin1(value).toDouble();
        result = dset->findAndGetString(DCM_Exposure, value);
        mAs = QString::fromLatin1(value).toDouble();
        result = dset->findAndGetString(DCM_ExposureTime, value);
        mS = QString::fromLatin1(value).toDouble();
        result = dset->findAndGetString(DCM_XRayTubeCurrent, value);
        mA = QString::fromLatin1(value).toDouble();

        result = dset->findAndGetFloat64(DCM_WindowWidth, winWidth);
        result = dset->findAndGetFloat64(DCM_WindowCenter, winCenter);
    }
}

const ushort *ImageInstance::getRawData() const
{
    const ushort *data = 0;
    ulong count;
    if (dcmff) dcmff->getDataset()->findAndGetUint16Array(DCM_PixelData, data, &count);
    return data;
}

const short *ImageInstance::getInterData()
{
    if ((!dcmImage) && dcmff) {
        dcmImage = new DicomImage(dcmff, dcmff->getDataset()->getOriginalXfer());
        if (dcmImage->getStatus() == EIS_Normal) {
            dcmImage->setWindow(0);
        } else {
            delete dcmImage;
            dcmImage = 0;
        }
    }

    return dcmImage?((const short *)dcmImage->getInterData()->getData()):0;
}

QImage ImageInstance::getPixmap()
{
    if ((!dcmImage) && dcmff) {
        dcmImage = new DicomImage(dcmff, dcmff->getDataset()->getOriginalXfer());
        if (dcmImage->getStatus() == EIS_Normal) {
            dcmImage->setWindow(0);
        } else {
            delete dcmImage;
            dcmImage = 0;
        }
    }
    if (dcmImage) {
        void *pDIB = 0;
        int size = dcmImage->createWindowsDIB(pDIB, 0, 0, 8, 0, 1);

        int w = dcmImage->getWidth();
        int h = dcmImage->getHeight();
        QImage image(w, h, QImage::Format_Grayscale8);
        for (int y = 0; y < h; ++y) {
            uchar *line = image.scanLine(y);
            int idx = y*w;
            for (int x = 0; x < w; ++x) {
                line[x] = ((uchar*)pDIB)[idx+x];
            }
        }

        delete pDIB;
        return image;
    }
    return QImage();
}

DcmFileFormat *ImageInstance::getFileFormat() const
{
    return dcmff;
}

bool ImageInstance::getImageSize(ulong &width, ulong &height) const
{
    if (dcmff) {
        width = imgWidth;
        height = imgHeight;
        return true;
    }
    return false;
}
